﻿using System;
using System.Collections.Generic;
using MessageSystem.Managed.Interface;
using MessageSystem.Default.Interface;
using MessageSystem.Default.infrastructure;

namespace MessageSystem.Default.implement
{
    unsafe public class MessageSystem : IMessageChannelFactory,IMessageSystem
    {
        public static MessageSystem Instance = new MessageSystem();

        public void Create(Managed.Infrastructure.Options op)
        {
            m_pSelector = new Selector();
            m_allAcceptor = new List<Acceptor>();
            m_allConnector = new List<Connector>();
            m_allFinishConnector = new List<Connector>();
            m_allChannels = new List<MessageChannel>();
            m_allLostChannels = new List<MessageChannel>();

            options.max_block_cache_size = op.max_block_cache_size;
            options.max_message_size = op.max_message_size;
            options.max_msg_cache_size = op.max_msg_cache_size;

            allocator.Instance.create();
        }

        public void ListenLocalSystem(String ip, UInt16 port, OnAccept a)
        {
            Default.implement.Acceptor acceptor = new Default.implement.Acceptor(this, m_pSelector,a);
            acceptor.Listen(ip, port);
            m_allAcceptor.Add(acceptor);
        }

        public void ConnectRemoteSystem(string ip, UInt16 port, OnConnectSuccess os, OnConnectFailed of)
        {
            Connector connector = new Connector(this,m_pSelector);
            connector.Connect(ip,port,os,of);
            m_allConnector.Add(connector);
        }

        public void Poll(int millsecond)
        {
            m_pSelector.Poll(millsecond);
            foreach (var a in m_allAcceptor)
            {
                a.Poll();
            }
            foreach (var c in m_allLostChannels)
            {
                m_allChannels.Remove(c);
            }
            m_allLostChannels.Clear();

            foreach (var c in m_allChannels)
            {
                c.Poll();
            }

            for (int i = 0; i < m_allConnector.Count;++i) 
            {
                Connector c = m_allConnector[i];
                if ( c.Poll() )
                {
                    m_allFinishConnector.Add(c);
                }
            }

            foreach (var c in m_allFinishConnector)
            {
                m_allConnector.Remove(c);
            }
            m_allFinishConnector.Clear();
        }

        public IMessageChannel Create(System.Net.Sockets.Socket socket)
        {
            MessageChannel result = new MessageChannel(socket, m_pSelector, this);
            m_allChannels.Add(result);
            return result;
        }

        public void Destroy(IMessageChannel channel)
        {
            m_allLostChannels.Add((MessageChannel)channel);
        }

        private Selector m_pSelector;
        private List<Acceptor> m_allAcceptor;
        private List<Connector> m_allConnector;
        private List<Connector> m_allFinishConnector;
        private List<MessageChannel> m_allChannels;
        private List<MessageChannel> m_allLostChannels;
    }
}
